package com.bos.controller;

import com.bos.dao.AnggaranDAO;
import com.bos.dao.PeriodeDAO;
import com.bos.dao.SekolahDAO;
import com.bos.dao.TahunDAO;
import com.bos.domain.Anggaran;
import com.bos.domain.Periode;
import com.bos.domain.Sekolah;
import com.bos.domain.Tahun;
import com.bos.editor.AnggaranEditor;
import com.bos.editor.PeriodeEditor;
import com.bos.editor.SekolahEditor;
import com.bos.editor.TahunEditor;
import com.bos.util.UrlUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: Latief
 * Date: 3/17/11
 * Time: 8:29 PM
 * To change this template use File | Settings | File Templates.
 */
@Controller
public class AnggaranController {

    private AnggaranDAO anggaranDAO;
    private PeriodeDAO periodeDAO;
    private TahunDAO tahunDAO;
    private SekolahDAO sekolahDAO;
    private RestTemplate restTemplate;
    /*private Credentials credentials;*/


    /* --------------------- Getter and Setter ---------------------*/

    /*public Credentials getCredentials() {
        return credentials;
    }

    @Autowired
    public void setCredentials(Credentials credentials) {
        this.credentials = credentials;
        if (restTemplate != null) {
            CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate.getRequestFactory();
            HttpClient client = factory.getHttpClient();
            client.getState().setCredentials(AuthScope.ANY, credentials);
        }
    }*/

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;

//        if (credentials != null) {
//            CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate.getRequestFactory();
//            HttpClient client = factory.getHttpClient();
//            client.getState().setCredentials(AuthScope.ANY, credentials);
//        }
    }

    @Autowired
    public void setAnggaranDAO(AnggaranDAO anggaranDAO) {
        this.anggaranDAO = anggaranDAO;
    }

    @Autowired
    public void setPeriodeDAO(PeriodeDAO periodeDAO) {
        this.periodeDAO = periodeDAO;
    }

    @Autowired
    public void setSekolahDAO(SekolahDAO sekolahDAO) {
        this.sekolahDAO = sekolahDAO;
    }

    @Autowired
    public void setTahunDAO(TahunDAO tahunDAO) {
        this.tahunDAO = tahunDAO;
    }

    /* -------------------------- Other Methods -------------------------- */

    @RequestMapping(value = "/sekolah/{npsn}/anggaran", method = RequestMethod.GET)
    public String index(ModelMap modelMap, @PathVariable("npsn") Sekolah sekolah) {
        modelMap.addAttribute("data", anggaranDAO.getBySekolah(sekolah));
        modelMap.addAttribute("sekolah", sekolah);

        return "anggaran/index";
    }

    @RequestMapping(value = "/sekolah/{npsn}/anggaran/new", method = RequestMethod.GET)
    public String create(ModelMap modelMap, @PathVariable("npsn") Sekolah sekolah) {
        Anggaran anggaran = new Anggaran();

        modelMap.addAttribute("anggaran", anggaran);
        modelMap.addAttribute("sekolah", sekolah);
        modelMap.addAttribute("tahunList", tahunDAO.getAll());

        return "anggaran/create";
    }

    @RequestMapping(value = "/sekolah/{npsn}/anggaran", method = RequestMethod.POST)
    public String save(@PathVariable("npsn") Sekolah sekolah, @Valid @ModelAttribute("anggaran") Anggaran anggaran, BindingResult result, ModelMap modelMap) {
        modelMap.addAttribute("sekolah", sekolah);
        if (anggaran == null) throw new IllegalArgumentException("A Product is required");
        if (result.hasErrors() || !UrlUtil.isPropHostAvailable()) {
            modelMap.addAttribute("anggaran", anggaran);
            modelMap.addAttribute("tahunList", tahunDAO.getAll());

            return "anggaran/create";
        }

        //Siapkan data baru yang akan dikirim ke host propinsi
        String restError = "";
        anggaran.setSekolah(sekolah);
        HttpEntity<Anggaran> httpEntity = new HttpEntity<Anggaran>(anggaran);

        //Kirim data baru dengan json ke host propinsi.
        String hostUrl = UrlUtil.HOST_PROPINSI_URL + "sekolah/{npsn}/anggaran.json";
        Map<String, Object> varUrl = new HashMap<String, Object>();
        varUrl.put("npsn", sekolah.getNpsn());
        try {
            ResponseEntity<Map> responseEntity = restTemplate.exchange(hostUrl, HttpMethod.POST, httpEntity, Map.class, varUrl);
            Map<String, Object> response = responseEntity.getBody();
            if (!(Boolean) response.get("success"))
                restError += hostUrl + "\n";
        } catch (Exception e) {
            e.printStackTrace();
            restError += hostUrl + "\n";
        }
        //atribute jika terjadi error saat melakukan penyimpanan ke database kabupaten.
        if (!restError.isEmpty())
            modelMap.addAttribute("restError", restError.trim());

        //Simpan ke database lokal
        anggaranDAO.save(anggaran);

        return "redirect:/anggaran/" + anggaran.getId();
    }


    @RequestMapping(value = "/anggaran/{id}", method = RequestMethod.GET)
    public String show(ModelMap modelMap, @PathVariable("id") Anggaran anggaran) {
        modelMap.addAttribute("data", anggaran);
        modelMap.addAttribute("sekolah", anggaran.getSekolah());

        return "anggaran/show";
    }

    @RequestMapping(value = "/sekolah/{npsn}/anggaran/{id}/delete", method = RequestMethod.GET)
    public String delete(ModelMap modelMap, @PathVariable("npsn") Sekolah sekolah, @PathVariable("id") Anggaran anggaran) {
        modelMap.addAttribute("sekolah", sekolah);

        if (!UrlUtil.isPropHostAvailable()) {
            return "redirect:/sekolah";
        }

        //Siapkan data yang akan dihapus ke host propinsi
        String restError = "";

        //Kirim data yang akan dihapus dengan json ke host propinsi.
        String hostUrl = UrlUtil.HOST_PROPINSI_URL + "sekolah/{npsn}/anggaran/periode/{periodeId}/delete.json";
        Map<String, Object> varUrl = new HashMap<String, Object>();
        varUrl.put("npsn", anggaran.getSekolah().getNpsn());
        varUrl.put("periodeId", anggaran.getPeriode().getId());
        try {
            ResponseEntity<Map> responseEntity = restTemplate.exchange(hostUrl, HttpMethod.GET, null, Map.class, varUrl);
            Map<String, Object> response = responseEntity.getBody();
            if (!(Boolean) response.get("success"))
                restError += hostUrl + "\n";
        } catch (Exception e) {
            e.printStackTrace();
            restError += hostUrl + "\n";
        }
        //atribute jika terjadi error saat melakukan penghapusan data di tiap host.
        if (!restError.isEmpty())
            modelMap.addAttribute("restError", restError.trim());

        //Hapus data lokal setelahnya.
        anggaranDAO.delete(anggaran);
        return "redirect:/sekolah/" + sekolah.getNpsn() + "/anggaran";
    }

    @RequestMapping(value = "/sekolah/{npsn}/anggaran/{id}/edit", method = RequestMethod.GET)
    public String edit(ModelMap modelMap, @PathVariable("id") Anggaran anggaran, @PathVariable("npsn") Sekolah sekolah) {
        modelMap.addAttribute("anggaran", anggaran);
        modelMap.addAttribute("tahunList", tahunDAO.getAll());
        modelMap.addAttribute("periodeList", periodeDAO.getByTahun(anggaran.getPeriode().getTahun()));
        modelMap.addAttribute("sekolah", sekolah);

        return "anggaran/edit";
    }

    @RequestMapping(value = "/sekolah/{npsn}/anggaran", method = RequestMethod.PUT)
    public String update(@PathVariable("npsn") Sekolah sekolah, @Valid @ModelAttribute("anggaran") Anggaran anggaranNew, BindingResult result, ModelMap modelMap) {
        modelMap.addAttribute("sekolah", sekolah);
        Anggaran anggaranOld = anggaranDAO.get(anggaranNew.getId());
        if (anggaranNew == null) throw new IllegalArgumentException("A Product is required");
        if (result.hasErrors() || !UrlUtil.isPropHostAvailable()) {
            modelMap.addAttribute("anggaran", anggaranNew);
            modelMap.addAttribute("tahunList", tahunDAO.getAll());
            modelMap.addAttribute("periodeList", periodeDAO.getByTahun(anggaranOld.getPeriode().getTahun()));
            return "anggaran/edit";
        }

        //Ambil data lama sebelum dilakukan perubahan data.
        //Siapkan data baru yang akan dikirim ke host propinsi
        String restError = "";
        anggaranNew.setSekolah(sekolah);
        HttpEntity<Anggaran> httpEntity = new HttpEntity<Anggaran>(anggaranNew);

        //Kirim data baru dengan json ke host propinsi.
        String hostUrl = UrlUtil.HOST_PROPINSI_URL + "sekolah/{npsn}/anggaran/periode/{periodeId}.json";
        Map<String, Object> varUrl = new HashMap<String, Object>();
        varUrl.put("npsn", sekolah.getNpsn());
        varUrl.put("periodeId", anggaranOld.getPeriode().getId());
        try {
            ResponseEntity<Map> responseEntity = restTemplate.exchange(hostUrl, HttpMethod.PUT, httpEntity, Map.class, varUrl);
            Map<String, Object> response = responseEntity.getBody();
            if (!(Boolean) response.get("success"))
                restError += hostUrl + "\n";
        } catch (Exception e) {
            e.printStackTrace();
            restError += hostUrl + "\n";
        }

        //atribute jika terjadi error saat melakukan penyimpanan ke database kabupaten.
        if (!restError.isEmpty())
            modelMap.addAttribute("restError", restError.trim());

        //simpan ke database lokal setelah semua database di semua host lain dirubah.
        anggaranDAO.merge(anggaranNew);

        return "redirect:/anggaran/" + anggaranNew.getId();
    }

    @InitBinder
    protected void initBinder(WebDataBinder binder) throws Exception {
        binder.registerCustomEditor(Sekolah.class, new SekolahEditor(sekolahDAO));
        binder.registerCustomEditor(Periode.class, new PeriodeEditor(periodeDAO));
        binder.registerCustomEditor(Anggaran.class, new AnggaranEditor(anggaranDAO));
        binder.registerCustomEditor(Tahun.class, new TahunEditor(tahunDAO));
    }
}
